package com.mti.epivisitemobile.view
{
	import com.google.zxing.BarcodeFormat;
	import com.google.zxing.BinaryBitmap;
	import com.google.zxing.BufferedImageLuminanceSource;
	import com.google.zxing.DecodeHintType;
	import com.google.zxing.Result;
	import com.google.zxing.client.result.ParsedResult;
	import com.google.zxing.client.result.ResultParser;
	import com.google.zxing.common.GlobalHistogramBinarizer;
	import com.google.zxing.common.flexdatatypes.HashTable;
	import com.google.zxing.qrcode.QRCodeReader;
	import com.mti.epivisitemobile.AppFacade;
	import com.mti.epivisitemobile.Constants;
	
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Matrix;
	import flash.media.Camera;
	import flash.media.Video;
	import flash.system.System;
	import flash.utils.Timer;
	
	import mx.events.FlexEvent;
	
	import org.puremvc.as3.patterns.mediator.Mediator;
	
	public class QRDecodeViewMediator extends Mediator
	{
		public static const NAME:String = "QRDecodeViewMediator";
		
		public function QRDecodeViewMediator(viewComponent:QRDecodeView)
		{
			super(NAME, viewComponent);
			
			view.addEventListener(FlexEvent.CREATION_COMPLETE, onViewComplete);
		}
		
		private var _camera:Camera = null;
		private var _video:Video = null;
		private var qrReader:QRCodeReader = null;
		private var _waitTimer:Timer = null;
		
		private function get cameraSize():Number
		{
			return view.videoContainer.width;
		}
		
		private function onViewComplete(event:FlexEvent):void
		{
			view.removeEventListener(FlexEvent.CREATION_COMPLETE, onViewComplete);
			
			if (Camera.isSupported == true)
			{
				_camera = Camera.getCamera();
				
				if ((_camera != null) && (_camera.muted == false))
				{
					_camera.setMode(cameraSize, cameraSize, 24);
					
					_video = new Video(cameraSize, cameraSize);
					_video.attachCamera(_camera);
					
					view.videoContainer.addChild(_video);
					
					qrReader = new QRCodeReader;
					
					_waitTimer = new Timer(500, 6);
					_waitTimer.addEventListener(TimerEvent.TIMER, onWaitTimerTick);
					_waitTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onWaitTimerComplete);
					_waitTimer.start();
					
					//view.videoContainer.addEventListener(MouseEvent.CLICK, onScanTimerTick);
				}
			}
		}
		
		// The UI will not refresh during the scanning, so we set a message during the last tick before the timer completion.
		private function onWaitTimerTick(event:TimerEvent):void
		{
			if (_waitTimer.currentCount == _waitTimer.repeatCount - 1)
				view.message.text = "Scan en cours";
		}
		
		private function onWaitTimerComplete(event:TimerEvent):void
		{
			var bmd:BitmapData = new BitmapData(cameraSize, cameraSize);
			bmd.draw(_video, null, null, null, null, true);
			_video.cacheAsBitmap = true;
			_video.cacheAsBitmapMatrix = new Matrix;
			decodeBitmapData(bmd, cameraSize, cameraSize);
			bmd.dispose();
			bmd = null;
			System.gc();
		}
		
		private function onContinueButtonClick(event:MouseEvent):void
		{
			sendNotification(Constants.SHOW_MEDIA_LIST);
		}
		
		private function get view():QRDecodeView
		{
			return viewComponent as QRDecodeView;
		}
		
		private function decodeBitmapData(bmpd:BitmapData, width:int, height:int):void
		{
			_waitTimer.stop();
			
			var lsource:BufferedImageLuminanceSource = new BufferedImageLuminanceSource(bmpd);
			var bitmap:BinaryBitmap = new BinaryBitmap (new GlobalHistogramBinarizer(lsource));
			
			var ht:HashTable = getAllHints();
			
			var res:Result = null;
			
			try
			{
				res = qrReader.decode(bitmap, ht);
			}
			catch (error:Error)
			{
				view.message.text = "Erreur";
				_waitTimer.reset();
				_waitTimer.start();
			}
			
			if (res != null)
			{
				_waitTimer.removeEventListener(TimerEvent.TIMER, onWaitTimerTick);
				_waitTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, onWaitTimerComplete);
				
				var result:String = ResultParser.parseResult(res).getDisplayResult();
				
				var data:Array = result.split("/");
				
				if ((data.length != 3) || (data[0] != "Epivisite"))
				{
					view.message.text = "Erreur";
				}
				
				sendNotification(Constants.LOAD_POI, result);
			}
		}
		
		private function getAllHints():HashTable
		{
			var ht:HashTable = new HashTable;
			ht.Add(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
			return ht;
		}
	}
}